<?php

require_once ("UserFile.php");

class UserFileHandler {

	//The directory where we will store and/or look for our files
	const dir = "UploadedFiles/";
	
	//Upload statuses
	const UPLOAD_ERROR = 4;
	const INVALID_FILE = 3;
	const FILE_EXIST = 2;
	const UPLOAD_OK = 1;
	
	//isValidFile status
	private $result = "";

	//Database info members
	private $DBConnection = null;
	private $TabelName = "userfiles";
	private $Class = "UserFile";
	const CLASSNAME = "UserFile";

	public function __construct(DBConnection $DBConnection, $DBPrefix) {
		$this -> DBConnection = $DBConnection;
		$this -> TabelName = $DBPrefix . $this -> TabelName;
	}
	
	/**
	 * 
	 * DISC - C | R | U | D
	 * 
	 */
	
	/**
	 * Function to read files from a given directory
	 * @access public
	 * @param -
	 * @return Array
	 * Returns array of all files in directory
	 */
	public function getAllFilesFromDisc() {
		$fileArray = array();

		// Open directory and read files untill done
		//Return all the files regardless of extension
		if (is_dir(FileUploadHandler::dir)) {
			if ($dh = opendir(FileUploadHandler::dir)) {
				while (($file = readdir($dh)) !== false) {
					//Just get the files with jpeg, jpg, gif or png extension
					$info = pathinfo($file);
					switch(strtolower($info['extension'])) {
						case 'jpeg' :
						case 'jpg' :
						case 'gif' :
						case 'png' :
							$fileArray[] = $file;
							break;
					}
				}
				closedir($dh);
			}
		}
		return $fileArray;
	}

	/**
	 * Function to save file to directory and DB
	 * @access public
	 * @param file, UserObject logged in user
	 * @return string containing upload status, ok or not ok
	 * Saves file to disk, restricted to gif, jpeg/pjpeg and png at this point
	 */
	public function saveFileToDisc($file, $loggedInUserId) {
		//Put users Id in filename so that users are not limited by other users filenames
		$file["name"] = $loggedInUserId . $file["name"];

		//If the file is ok
		if ($this -> isValidFile($file)) {
			//Create an UserFile object and send to DB
			$userFile = UserFile::create($loggedInUserId, $file["name"]);
			//If we can store it in DB, save file to disk
			if ($this -> insertUserFile($userFile) !== false) {
				move_uploaded_file($_FILES["file"]["tmp_name"], "UploadedFiles/" . $file["name"]);
			}
		}
		//Return result that is generated by isValidFile($file)
		return $this -> result;
	}
	
	/**
	 * Function to delete file from disk
	 * @access private
	 * @param UserFile
	 * @return bool
	 */
	private function deleteFileFromDisc(UserFile $userFile) {
		$fileName = "./UploadedFiles/" . $userFile -> FileName;
		if(file_exists($fileName)){
			return unlink($fileName);
		}
		return false;
	}
	
	/**
	 * Funtion to validate file before saving
	 * @access private
	 * @param file - $file
	 * @return bool If file is ok or not
	 */
	private function isValidFile($file) {
		if (!(($file["type"] == "image/gif") || ($file["type"] == "image/png") || ($file["type"] == "image/jpeg") || ($file["type"] == "image/pjpeg")) && ($file["size"] < 500000)) {
			$this -> result = self::INVALID_FILE;
			return false;
		} elseif ($file["error"] > 0) {
			$this -> result = self::UPLOAD_ERROR;
			return false;
		} elseif (file_exists("UploadedFiles/" . $file["name"])) {
			//File exist, deal with it (or not)!
			$this -> result = self::FILE_EXIST;
			return false;
		} else {
			$this -> result = self::UPLOAD_OK;
			return true;
		}
	}

	/**
	 * 
	 * DB - C | R | U | D
	 * 
	 */

	/**
	 * Function to create table
	 * @access public
	 * @param -
	 * @return bool
	 */
	public function createTable() {
		$sql = "CREATE TABLE IF NOT EXISTS `" . $this -> TabelName . "` (
		  `userId` int(11) DEFAULT NULL,
		  `FileName` varchar(250) DEFAULT NULL,
		  KEY `userId` (`userId`)
		) ENGINE=InnoDB DEFAULT CHARSET=latin1;";

		return $this -> DBConnection -> RunQuery($sql);
	}

	/**
	 * Function to drop table from DB
	 * @access public
	 * @param -
	 * @return bool
	 */
	public function removeTable() {
		return $this -> DBConnection -> dropTable($this -> TabelName);
	}

	/**
	 * Function to get all files by user ID
	 * @access public 
	 * @param UserId
	 * @return Array where key => filename value => userId
	 */
	public function getFilesByUserId($a_userId) {
		$sql = "SELECT * FROM $this->TabelName WHERE userId = ?";

		$stmt = $this -> DBConnection -> Prepare($sql);

		$stmt -> bind_param("i", $a_userId);

		$array = $this -> fetchObjects($stmt, "FileName");

		return $array;

	}
	
	/**
	 * Function to insert a new UserFile into Table
	 * @access public
	 * @param UserFile object
	 * @return bool
	 */
	public function insertUserFile(UserFile $a_userFile) {
		$sql = "INSERT INTO $this->TabelName (userId, FileName) VALUES(?,?)";

		$stmt = $this -> DBConnection -> Prepare($sql);

		$stmt -> bind_param("is", $a_userFile -> userId, $a_userFile -> FileName);

		if ($stmt === FALSE) {
			return false;
		}

		if ($stmt -> execute() === false) {
			LogHandler::logError("Could not Insert userFile: " . $stmt);
			return false;
		}

		$stmt -> close();
		return true;
	}
	
	/**
	 * Function that will remove all files uploaded by a user
	 * Will get all files by given userId and then remove them one at the time from DB and disc
	 * @access public
	 * @param UserId
	 * @return bool
	 */
	public function deleteAllFilesByUserId($a_userId) {
		$filesArray = $this -> getFilesByUserId($a_userId);

		foreach ($filesArray as $key => $file) {
			$this -> deleteUserFile($file);
		}

		return true;
	}
	
	/**
	 * Function that will remove one file at the time from user
	 * @access public
	 * @param UserFile Object
	 * @return bool
	 */
	public function deleteUserFile(UserFile $userFile) {
		//Start by removing the file from disk, if not ok, return false
		if (!$this -> deleteFileFromDisc($userFile)) {
			return false;
		}

		$sql = "DELETE FROM $this->TabelName WHERE userId = ? AND FileName = ?";

		$stmt = $this -> DBConnection -> prepare($sql);

		$stmt -> bind_param("is", $userFile -> userId, $userFile -> FileName);

		if ($stmt === false) {
			return false;
		}

		if ($stmt -> execute() === false) {
			LogHandler::logError("Could not Delete userFile: " . $stmt);
			return false;
		}

		$stmt -> close();
		return true;
	}

	/**
	 * Function to call DB and get result as objects in array
	 * @access public
	 * @param SQLStatement, Indexer = witch member to index array by
	 * @return array with UserFileObjects
	 */
	public function fetchObjects($stmt, $indexer) {
		$retArray = array();
		if($stmt->execute() === false){
			LogHandler::logError("fetchObjects in UserFile can not execute! ". $stmt);
			return $retArray;
        }
		
		$stmt->bind_result($userId, $fileName);
		
		while($stmt->fetch()){
			$userFile = UserFile::create($userId, $fileName);
			$retArray[$userFile->$indexer] = $userFile;
		}
		
		$stmt->close();
		return $retArray;
	}
}
